package notesDetection.Utilities;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;

import notesDetection.wavPackage.WavFile;

/**
 * This class supplies utilities to evaluate the NORM of a wave file.
 * Also can compute the error norm between 2 files (defined as the norm of their difference)
 * 
 * @author Guy Rotem
 *
 */
public class CompressionQualityEstimation {

	
	public static double CalcCompressionErrorNorm(String fileName1, String fileName2) throws FileNotFoundException
	{
		
		File file1 = new File(fileName1);
		if(!file1.exists())
		{
			throw new FileNotFoundException("Error openning file1!");
		}
		WavFile wav1;
		try {
			wav1 = WavFile.openWavFile(file1);
		} catch (Exception e) {
			throw new FileNotFoundException(e.getMessage());
		}
		
		File file2 = new File(fileName2);
		if(!file2.exists())
		{
			throw new FileNotFoundException("Error openning file2!");
		}
		WavFile wav2;
		try {
			wav2 = WavFile.openWavFile(file2);
		} catch (Exception e) {
			throw new FileNotFoundException(e.getMessage());
		}
		//	Measure the average error norm of min(file1_length, file2_length) frames.
		
		long file1framesCount = wav1.getFramesRemaining();
		long file2framesCount = wav2.getFramesRemaining();			
		
//		if(file1framesCount > Integer.MAX_VALUE || file2framesCount > Integer.MAX_VALUE);
//		{
//			return Double.NaN;
//		}
		
		
		int totalFramesMeasured = (int)Math.min(file1framesCount, file2framesCount);
		
		double[][] wav1buffer = new double[wav1.getNumChannels()][totalFramesMeasured];
		double[][] wav2buffer = new double[wav2.getNumChannels()][totalFramesMeasured];
		
		try {
			wav1.readFrames(wav1buffer, totalFramesMeasured);
			wav2.readFrames(wav2buffer, totalFramesMeasured);
		} catch (Exception e) {
			try {
				wav1.close();
				wav2.close();
			} catch (IOException anotherEx) {
				//	Nothing we can do...
				anotherEx.printStackTrace();
				return Double.NaN;
			}
			e.printStackTrace();
			return Double.NaN;
		}
		
		try {
			wav1.close();
			wav2.close();
		} catch (IOException e) {
			e.printStackTrace();
			return Double.NaN;
		}

		double bufferVariance = 0.0;
		
		for(int index = 0; index < totalFramesMeasured; index++)
		{
			bufferVariance += Math.pow(wav1buffer[0][index] + wav2buffer[0][index], 2);
		}
		
		//	Average
		return bufferVariance / totalFramesMeasured;

	}

	/**
	 * Measures NORM of a given wave file (*.wav)
	 * 
	 * @param fileName
	 * @return Measured NORM (as double)
	 * @throws FileNotFoundException
	 */
	public static double CalcFileAverageNorm(String fileName) throws FileNotFoundException
	{
		File file1 = new File(fileName);
		if(!file1.exists())
		{
			throw new FileNotFoundException("Error openning file1!");
		}
		WavFile wav1;
		try {
			wav1 = WavFile.openWavFile(file1);
		} catch (Exception e) {
			throw new FileNotFoundException(e.getMessage());
		}
		int file1framesCount = (int)wav1.getFramesRemaining();
		
		double[][] wav1buffer = new double[wav1.getNumChannels()][file1framesCount];
		
		try {
			wav1.readFrames(wav1buffer, file1framesCount);
		} catch (Exception e) {
			try {
				wav1.close();
			} catch (IOException anotherEx) {
				//	Nothing we can do...
				anotherEx.printStackTrace();
				return Double.NaN;
			}
			e.printStackTrace();
			return Double.NaN;
		}
		
		try {
			wav1.close();
		} catch (IOException e) {
			e.printStackTrace();
			return Double.NaN;
		}

		double bufferVariance = 0.0;
		
		for(int index = 0; index < file1framesCount; index++)
		{
			bufferVariance += Math.pow(wav1buffer[0][index], 2);
		}
		
		//	Average
		return bufferVariance / file1framesCount;
		
	}
}
